#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include "NetCapture.h"
#include "Svc_BaseTypedef.h"
#include "protocol.h"
#include "hi_appcomm_log.h"
#include "pthread.h"
#include "protocol.h"
#include "Sqlist_List.h"
#include "app_common.h"
#include "MediaPack.h"
#include "OnlineToolCallBack.h"
#include "IBT_List.h"
#include "Video.h"
#include "OsdDraw.h"


//
enum RTFrameBeginEndFlag
{
	PACK_CONTAIN_FRAME_NONHT = 0, /*无头无尾,不含帧头或帧尾 */
	PACK_CONTAIN_FRAME_HEAD, /*只有头*/
	PACK_CONTAIN_FRAME_TRAIL,/*只有尾*/
	PACK_CONTAIN_FRAME_HEADTRAIL,/* 包含帧头和帧尾 */
	PACK_CONTAIN_FRAME_MOTION_HEAD = 5,
	PACK_CONTAIN_FRAME_NUM,
	
};

enum RTPackTypeFlag
{
	PACK_TYPE_FRAME_P=0,
	PACK_TYPE_FRAME_I,
	PACK_TYPE_FRAME_B,
	PACK_TYPE_FRAME_AUDIO,
	PACK_TYPE_FRAME_JEPG,
	PACK_TYPE_FRAME_MOTION,
	PACK_TYPE_FRAME_NUM,
	PACK_TYPE_FRAME_NULL=0xff,/*结束，无数据*/
};



CCapture_List gCapture_List;
Capture_config gCapture_config;


/*
 *函数说明:捕获和链接人数等初始化
 */
void Net_gCaptureList_Init()  
{
	gCapture_config.frame_rate=15;								//15帧
	gCapture_config.pic_height=720;								//高度720
	gCapture_config.pic_width=480;								//宽度480
	
	gCapture_List.m_Capture_Number=0;							//捕获开启人数
	gCapture_List.m_Connect_Number=0;							//服务链接人数
	gCapture_List.m_Capture_Swich=FALSE;						//是否开启捕获开关
	pthread_mutex_init(&(gCapture_List.m_Capture_hmutex),NULL);	
	List_Init(&(gCapture_List.m_Capture_Head.Head));			//初始化表头	
	IBT_List_QueueInit(&(gCapture_List.m_Packet_Queue));		//初始化队列
	
}


/*
 *  产测视频配置设置接口：
 *  height：		图像高度
 *  width:  	图像宽度
 *  frame_rate: 图像帧率
 */
void NetCaptureSetConfig(int height,int width,int frame_rate)
{
	gCapture_config.frame_rate=frame_rate;
	gCapture_config.pic_height=height;
	gCapture_config.pic_width=width;

}

/*
 *  产测视频配置获取接口：
 *  height：		图像高度
 *  width:  	图像宽度
 *  frame_rate: 图像帧率
 */

void NetCaptureGetConfig(int *height,int *width,int *frame_rate)
{
	*height=gCapture_config.pic_height;
	*width=gCapture_config.pic_width;
	*frame_rate=gCapture_config.frame_rate;
}






/*
 * 函数说明:释放掉上传完毕的数据包
 */

void Realse_Packet(CNet_Packet **Packet)
{

	if(*Packet!=NULL)
	{
		unsigned int count;
		pthread_mutex_lock(&((*Packet)->m_mutex));
		(*Packet)->m_pakc_num--;
		count=(*Packet)->m_pakc_num;	
		pthread_mutex_unlock(&((*Packet)->m_mutex));
		if(count==0)
		{
			pthread_mutex_destroy(&((*Packet)->m_mutex));
			free((*Packet)->m_Buffer);
			free((*Packet));
			(*Packet)=NULL;
		}	
		
	}
}

/*
 * 函数说明:释放掉上传完毕的数据包
 */
void SendRelease(const struct tagMsgHdr *msg)
{
	CNet_Packet **Packet=(CNet_Packet **)(msg->context);
	if(*Packet!=NULL)
	{
		unsigned int count;
		pthread_mutex_lock(&((*Packet)->m_mutex));
		(*Packet)->m_pakc_num--;
		count=(*Packet)->m_pakc_num;	
		pthread_mutex_unlock(&((*Packet)->m_mutex));
		if(count==0)
		{
			pthread_mutex_destroy(&((*Packet)->m_mutex));
			free((*Packet)->m_Buffer);
			free((*Packet));
			(*Packet)=NULL;
		}	
		
	}
}


/*
 * 函数说明:为视频编码数据添加私有头   0为P帧，1为I帧
 */
int FormStandHead(unsigned char *buf,int framelen,int headtype,time_t times)
{
	int pic_width=gCapture_config.pic_width;	
	int pic_height=gCapture_config.pic_height;
	int frame_rate=gCapture_config.frame_rate;
	int head_len=0;
	unsigned int frame_head[5];
	
		
	if(headtype==PACK_TYPE_FRAME_I)//目前只有这个两个帧  ,I帧和P帧
	{
	time_t seconds;
	struct tm *ltm;
	unsigned int xrwh,datetime;
	seconds=time(NULL);				
	ltm=localtime(&seconds);		//这里应该改为编码时间
	if(ltm->tm_year < 100)
        {
            ltm->tm_year = 0;
        }
        else
        {
            ltm->tm_year -= 100;
        }
        
       datetime = (ltm->tm_sec) | (ltm->tm_min  << 6) | (ltm->tm_hour << 12) | (ltm->tm_mday << 17)
                    | ((ltm->tm_mon + 1)  << 22) | ((ltm->tm_year) << 26);
       xrwh = 2 | (frame_rate << 8);

       	frame_head[0] = 0xAD010000;
       	frame_head[1] = xrwh;
       	frame_head[2] = pic_width | (pic_height << 16);
       	frame_head[3] = datetime;
       	frame_head[4] = framelen;
     	memcpy(buf, frame_head, 5*sizeof(unsigned int));
    	 head_len = 20;
	}
	else if(headtype==PACK_TYPE_FRAME_P)  //P帧 PACK_TYPE_FRAME_P
	{
		frame_head[0] = 0xAC010000;
        frame_head[1] = framelen;
        memcpy(buf, frame_head, 2*sizeof(unsigned int));
        head_len = 8;
	}
	else if(headtype == PACK_TYPE_FRAME_AUDIO) //音频头
    {
        frame_head[0] = 0xA0010000;//
        frame_head[1] = 14 | (2 << 8) | (framelen << 16);
        memcpy(buf, frame_head, 2*sizeof(unsigned int));
        head_len = 8;
    }
	
	return head_len;


}


/* 
 *函数说明：数据包打包和发送函数 
 */
void NetCapture_Send(struct conn *m_conn,CNet_Packet** P_Packet)
{
	if(m_conn==NULL)return ;
	if(m_conn->pCapture->m_MonitorState==0)return ;  
	//printf("--1--\n");
	 static unsigned char frame_local2net[] =
    {
       	0x00,    //!PACK_TYPE_FRAME_P
        0x10,    //!PACK_TYPE_FRAME_I,
        0x20,    //!PACK_TYPE_FRAME_B,
        0x30,    //!PACK_TYPE_FRAME_AUDIO,
        0x40,    //!PACK_TYPE_FRAME_JEPG,
        0x50,    //!PACK_TYPE_FRAME_MOTION,
        0x60,    //!PACK_TYPE_FRAME_EE
        0x70,    //!PACK_TYPE_FRAME_EF
        0xf0,    //!PACK_TYPE_FRAME_NUM,
        0xf0,    //!PACK_TYPE_FRAME_NULL=0xff,
    };
	if((*P_Packet)==NULL)return ;
	const unsigned long packetLen	=	(*P_Packet)->m_length;
	static int ptk_slice_len 		= 	1024 * 32;
	DVRIP ip;
	msghdr_t msghdr[2] ;
	int num 	= packetLen / ptk_slice_len;
	int slice 	= packetLen % ptk_slice_len;
	int index 	= 0;
	while(index < num)
		{
		memset(&ip, 0, sizeof(ip));
        memset(&msghdr, 0, sizeof(msghdr));
        ip.dvrip_cmd = ACK_CHAN_MONIT;
        ip.dvrip_extlen= ptk_slice_len;
        ip.dvrip_p[0]   = 0;
        ip.dvrip_p[1]   = 0x00;
		ip.dvrip_p[2] 	= frame_local2net[(*P_Packet)->Frame_Type];
		ip.dvrip_p[3] 	= 0xff;
        ip.dvrip_p[16]  = 0;

		if (0 == slice)
            {
                if (1 == num)
                {
                    ip.dvrip_p[2] = (ip.dvrip_p[2] | PACK_CONTAIN_FRAME_HEADTRAIL);
                }
				else if (0 == index)
				{
				    ip.dvrip_p[2] = (ip.dvrip_p[2] | PACK_CONTAIN_FRAME_HEAD);
				}
				else if(index == num -1)
				{
				    ip.dvrip_p[2] = (ip.dvrip_p[2] | PACK_CONTAIN_FRAME_TRAIL);
				}
				else
				{
				    ip.dvrip_p[2] = (ip.dvrip_p[2] | PACK_CONTAIN_FRAME_NONHT);
				}
            }
        else 
			{
				if (0 == index)
				{
				    ip.dvrip_p[2] = (ip.dvrip_p[2] | PACK_CONTAIN_FRAME_HEAD);
				}
				else
				{
				    ip.dvrip_p[2] = (ip.dvrip_p[2] | PACK_CONTAIN_FRAME_NONHT);
				}
			}
			pthread_mutex_lock(&((*P_Packet)->m_mutex));
			(*P_Packet)->m_pakc_num++;
			pthread_mutex_unlock(&((*P_Packet)->m_mutex));
			msghdr[0].msgCmd   = ACK_CHAN_MONIT;
	        msghdr[0].chn      = 0;
	        msghdr[0].buf      = &ip;
	        msghdr[0].buf_len  = sizeof(ip);
	        msghdr[0].msg_flags= MSG_FLAGS_MORE;
	        msghdr[0].next     = &msghdr[1];

	        msghdr[1].msgCmd   = ACK_CHAN_MONIT;
	        msghdr[1].chn      = 0;
	        msghdr[1].buf      = (*P_Packet)->m_Buffer + index * ptk_slice_len;
	        msghdr[1].buf_len  = ptk_slice_len;
	        msghdr[1].msg_flags= 0;
	        msghdr[1].callback = SendRelease;
	        msghdr[1].context  = P_Packet;
	        msghdr[1].iFrameFlag = PKT_FULL_FRAME;

			DvrNetSendChain(m_conn, msghdr);
	        NetDvrSendOtherQueue(m_conn,0, ACK_CHAN_MONIT);
        	index++;
		}
		if (slice > 0)
		{
			memset(&ip, 0, sizeof(ip));
	        memset(&msghdr, 0, sizeof(msghdr));
	        ip.dvrip_cmd = ACK_CHAN_MONIT;
	        ip.dvrip_extlen= slice;
	        ip.dvrip_p[0]   = 0;
	        ip.dvrip_p[1]   = 0x00; 
			ip.dvrip_p[2] 	= frame_local2net[(*P_Packet)->Frame_Type];
			ip.dvrip_p[3] 	= 0xff;
	        ip.dvrip_p[16]  = 0;  //0或者如果stream不为0则为4
			if (0 == num)
			{
			    ip.dvrip_p[2] = (ip.dvrip_p[2] | PACK_CONTAIN_FRAME_HEADTRAIL);
			}
			else
			{
			    ip.dvrip_p[2] = (ip.dvrip_p[2] | PACK_CONTAIN_FRAME_TRAIL);
			}
			pthread_mutex_lock(&((*P_Packet)->m_mutex));
			(*P_Packet)->m_pakc_num++;
			pthread_mutex_unlock(&((*P_Packet)->m_mutex));
	        msghdr[0].msgCmd   = ACK_CHAN_MONIT;
	        msghdr[0].chn      = 0;
	        msghdr[0].buf      = &ip;
	        msghdr[0].buf_len  = sizeof(ip);
	        msghdr[0].msg_flags= MSG_FLAGS_MORE ;
	        msghdr[0].next     = &msghdr[1];

	        msghdr[1].msgCmd   = ACK_CHAN_MONIT;
	        msghdr[1].chn      = 0;
	        msghdr[1].buf      = (*P_Packet)->m_Buffer + num * ptk_slice_len;
	        msghdr[1].buf_len  = slice;
	        msghdr[1].msg_flags= 0;
	        msghdr[1].callback = SendRelease;
	        msghdr[1].context  = P_Packet;
	        msghdr[1].iFrameFlag = PKT_FULL_FRAME;

	        DvrNetSendChain(m_conn, msghdr);
	        NetDvrSendOtherQueue(m_conn,0, ACK_CHAN_MONIT);
		}
		return ;
}



/* 
 *	函数说明：上传视频,直接上传视频，更新数据有另一条线程
 */
void *NetCapture_UpLoad(void *arg)
{	//在上传中两次遍历，如果包都上传完毕m_ref为0 则free掉包，上数据包锁
	pthread_detach(pthread_self());
	SET_THREAD_NAME("NetCapture_UpLoad");
	List_Head *Conn_Pos;
	IBTList * IBT_Pos;
	CCapture *PSCapture;
	CNet_Packet *Packet;
	bool bSleep=TRUE;
	unsigned int count_sleep = 0;
	
	VideoGetOpsHandle()->request_idr_frame(0);
	
	while(gCapture_List.m_Capture_Swich==TRUE)
	{
				bSleep=TRUE;
				
					IBT_List_PopQueueFromHead(&(gCapture_List.m_Packet_Queue),&(gCapture_List.m_Packet_Queue.queue),&IBT_Pos);
					if(IBT_Pos!=NULL)
					{	
						//Packet=container_of(IBT_Pos,CNet_Packet,queue);
						Packet=List_Enter(IBT_Pos,CNet_Packet,queue);
						pthread_mutex_lock(&(gCapture_List.m_Capture_hmutex));//防止在访问的时候退出登录
						List_For_Each(Conn_Pos,&(gCapture_List.m_Capture_Head.Head))
						{//发送给每个用户
							if(Conn_Pos==NULL)continue;
							PSCapture=List_Enter(Conn_Pos, CCapture, Head);
							//if(PSCapture==NULL)continue;
							NetCapture_Send(PSCapture->m_conn,&Packet);
							bSleep=FALSE;
						}
						pthread_mutex_unlock(&(gCapture_List.m_Capture_hmutex));
						Realse_Packet(&Packet);
					}
					 if( bSleep )
			        {
			            count_sleep++;
			            if( count_sleep > 0 )
			            {
			                usleep(10000);
			                count_sleep = 0;
			            }
			        }
			        else
			        {
			           count_sleep = 0;
			        }

				
	}
	while(1)  //弹出和释放空余数据包
	{
		IBT_List_PopQueueFromHead(&(gCapture_List.m_Packet_Queue),&(gCapture_List.m_Packet_Queue.queue),&IBT_Pos);
		if(IBT_Pos==NULL)break;
		Packet=List_Enter(IBT_Pos,CNet_Packet,queue);
		Realse_Packet(&Packet);
	}
	pthread_exit(0);
	return 0;
}

/* 
 *	函数说明：创建上传视频线程
 */

void NetCapture_CreateThread()
{
	pthread_create(&gCapture_List.m_Update_pthread_Id,NULL,NetCapture_UpLoad,NULL);
}

/* 
 *	函数说明：为捕获添加成员 gCapture_List.m_Capture_Head
 */
void NetCapture_AddNumber(struct conn *p_conn)//添加成员
{
	
	CCapture *P_Capture=(CCapture *)malloc(sizeof(CCapture));
	if(P_Capture==NULL)
	{
	LOGE("NetCapture_AddNumber Error \n");
	return ;
	}
	P_Capture->m_conn=p_conn;
	P_Capture->m_MonitorState=0;
	p_conn->pCapture=P_Capture;//互相绑定上
	pthread_mutex_lock(&(gCapture_List.m_Capture_hmutex));
	List_Add_Tail(&(P_Capture->Head),&(gCapture_List.m_Capture_Head.Head));
	pthread_mutex_unlock(&(gCapture_List.m_Capture_hmutex));

}

/* 
 *	函数说明：为捕获删除成员 gCapture_List.m_Capture_Head
 */
void NetCapture_DeleteNumber(struct conn *p_conn)
{
	//遍历总队列，符合条件，弹出总队列
	//第一个丢指针，第二个丢总表，第三个丢queue;
	List_Head *Pos,*Next;
	CCapture *P_Capture;	
	
	pthread_mutex_lock(&(gCapture_List.m_Capture_hmutex));
	List_For_Each_Safe(Pos,Next,&(gCapture_List.m_Capture_Head.Head))
	{
		
		P_Capture=List_Enter(Pos,CCapture,Head);
		if(P_Capture&&(P_Capture->m_conn==p_conn))//匹配上,free掉，弹出总表
		{
		P_Capture->m_conn=NULL;
		List_Del(Pos);
		free(P_Capture);//释放掉结点地址
		break;
		}
	}
	pthread_mutex_unlock(&(gCapture_List.m_Capture_hmutex));			//弹出表中
	
}



static inline int GetTimeSec(void)
{
    return time(NULL);
}

/* 
 *	函数说明：为捕获添加视频包 gCapture_List.m_Packet_Queue.queue
 */
 void OnlineCapture_Updata(void *m_buff,unsigned int Size,time_t time,char Frame_Type)
{  

	if(gCapture_List.m_Capture_Number>0&&gCapture_List.m_Capture_Swich==TRUE)
	{
        //LOGI("Test\n");
        static time_t lastTime = 0;
        if (lastTime == 0 || GetTimeSec() >= lastTime + 5) {
            lastTime = GetTimeSec();
            PowerSetSocSleepTime(AV_TRUE, 15); //维活
        }
        
		int head_len;
		CNet_Packet *Packet=(CNet_Packet *)malloc(sizeof(CNet_Packet));
		if(Packet==NULL)
		{
		LOGE(" Malloc error ");
		return ;
		}
		memset(Packet,0,sizeof(CNet_Packet));
		Packet->m_Buffer=(unsigned char *)malloc(Size+50);
		if(Packet->m_Buffer==NULL)
		{
		free(Packet);
		LOGE("m_Buffer malloc error \n");
		return ;
		}
		memset(Packet->m_Buffer,0,Size+50);
		head_len=FormStandHead(Packet->m_Buffer,Size,Frame_Type,time);
		memcpy((Packet->m_Buffer)+head_len,(unsigned char *)m_buff,Size);
		Packet->Frame_Type=Frame_Type;
		Packet->m_length=Size+head_len;
		Packet->m_pakc_num=1;  //初始化为1
		pthread_mutex_init(&(Packet->m_mutex),NULL);
		IBT_List_PushQueueToTail(&(gCapture_List.m_Packet_Queue),&(gCapture_List.m_Packet_Queue.queue),&(Packet->queue));//添加到队列中
	
	}
}


/* 
 *	函数说明：开启捕获线程
 */
void NetCapture_start(struct conn *p_conn) //开始该通道的上传捕获
{	
	//LOGI("In The NetCapture_start \n");
	NetCapture_AddNumber(p_conn);//注册捕获视频流成员
	gCapture_List.m_Capture_Number++;
	p_conn->pCapture->m_MonitorState=1;
	if(gCapture_List.m_Capture_Swich==FALSE)
	{
	gCapture_List.m_Capture_Swich=TRUE;
	NetCapture_CreateThread();
	}

#ifdef FAC_PIR_OSD_SHOW
    OsdDrawPirStart();
#endif /* FAC_PIR_OSD_SHOW */

}

/* 
 *	函数说明：关闭捕获线程
 */

void NetCapture_Stop(struct conn *p_conn) //结束该通道的上传
{
	//捕获成员注销在	
	if(p_conn==NULL)return;			//防止非常规退出产测
	//if(p_conn->pCapture)return;
	//if(p_conn->pCapture->m_MonitorState==1)
	//{
	if(gCapture_List.m_Capture_Number>0)
		gCapture_List.m_Capture_Number--;
	//	p_conn->pCapture->m_MonitorState=0;
		//NetCapture_DeleteNumber(p_conn);
	//}
	if(gCapture_List.m_Capture_Swich==TRUE&&gCapture_List.m_Capture_Number==0)
	{
		gCapture_List.m_Capture_Swich=FALSE; //没有对象不需要更新数据，获取视频流中数据
	}
}




/*
 * 函数说明:开启用户视频捕获或者关闭
 */
int Capture_FilterCallback(struct conn *c, DVRIP *pHead)
{

	if(NULL==pHead||pHead->dvrip_cmd!=REQ_CHAN_SWTCH)
	return 0;//不是视频命令


    if(gCapture_List.m_Capture_Number>50)return -1;//最大人数

    if((pHead->dvrip_p[18])==0)//EnMonMode_Tcp模式
    {

		 if(pHead->dvrip_p[0])
		 {
		 //开启产测视频传输			 
			NetCapture_start(c);
		 }
		 else 
		 {
		 //关闭产测视频传输			 
		 	NetCapture_Stop(c);
		 }
    }
	return 0;
}





















